package com.supreme.studyserver.service;

import com.supreme.studyserver.proxy.ICoder;
import com.supreme.studyserver.proxy.OneLevelCoder;
import com.supreme.studyserver.proxy.TwoLevelCoder;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.stereotype.Service;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

@Service
public class ProxyCoderService {

    public void simpleDemo() {
        final OneLevelCoder oneLevelCoder = new OneLevelCoder();
        oneLevelCoder.writeCode("oneLevelCoder");

        final TwoLevelCoder twoLevelCoder = new TwoLevelCoder();
        twoLevelCoder.writeCode("twoLevelCoder");

        final Class<? extends OneLevelCoder> oneLevelCoderClass = oneLevelCoder.getClass();
        ICoder coder1 = (ICoder) Proxy.newProxyInstance(oneLevelCoderClass.getClassLoader(), oneLevelCoderClass.getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//                final Object invoke = method.invoke(oneLevelCoder, args);
                return false;
            }
        });
        coder1.reviewCode();

        /*final Class<? extends TwoLevelCoder> twoLevelCoderClass = twoLevelCoder.getClass();
        ICoder coder2 = (ICoder) Proxy.newProxyInstance(twoLevelCoderClass.getClassLoader(), twoLevelCoderClass.getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                return null;
            }
        });
        coder2.reviewCode();*/
    }

    public void demoProxyFactory() {
        final OneLevelCoder oneLevelCoder = new OneLevelCoder();
        oneLevelCoder.writeCode("oneLevelCoder");

        final TwoLevelCoder twoLevelCoder = new TwoLevelCoder();
        twoLevelCoder.writeCode("twoLevelCoder");

        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.setTarget(oneLevelCoder);

        proxyFactory.addAdvice(new MethodInterceptor() {
            @Override
            public Object invoke(MethodInvocation methodInvocation) throws Throwable {
                System.out.println("invoke first");
//                methodInvocation.proceed();
                return true;
            }
        });
        proxyFactory.addAdvice(new MethodInterceptor() {
            @Override
            public Object invoke(MethodInvocation methodInvocation) throws Throwable {
                System.out.println("invoke second");
                return methodInvocation.proceed();
            }
        });

        ICoder coder = (ICoder) proxyFactory.getProxy();
        coder.reviewCode();
    }
}
